package com.scut.scutzone.service.impl;

import com.scut.scutzone.config.HttpSessionAttribute;
import com.scut.scutzone.dao.CommentAccess;

import com.scut.scutzone.dao.PostAccess;

import com.scut.scutzone.dao.FollowAccess;

import com.scut.scutzone.dao.UserAccess;
import com.scut.scutzone.entity.Comment;
import com.scut.scutzone.entity.Follow;
import com.scut.scutzone.entity.Post;
import com.scut.scutzone.entity.User;
import com.scut.scutzone.exception.BusinessException;
import com.scut.scutzone.service.DatabaseService;
import com.scut.scutzone.util.FileUtil;
import com.scut.scutzone.util.SZUtil;
import com.scut.scutzone.vo.domain.FollowModel;
import com.scut.scutzone.vo.domain.UserSearchResult;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
//import sun.security.jgss.GSSCaller;


import java.sql.Timestamp;
import java.util.ArrayList;

import java.util.AbstractMap;
import java.util.HashMap;

import java.util.List;
import java.util.Map;

import static com.scut.scutzone.util.SZUtil.getRealImgsName;

/**
 * @author: lifeng Chan
 * @date: 2021/4/29 13:27
 * @description:
 */
@Service
public class DatabaseServiceImpl implements DatabaseService {

    @Autowired
    private CommentAccess commentAccess;
    @Autowired
    private UserAccess userAccess;
    @Autowired
    private PostAccess postAccess;
    @Autowired
    private FollowAccess followAccess;


    @Override
    public Map.Entry<String, Integer> createUser(String username, String password) throws BusinessException {
        if(username==null||password==null||username.isEmpty()||password.isEmpty())
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.toString());
        User user=userAccess.getUserByName(username);
        if(user!=null)
            throw new BusinessException(409,"用户已存在");
        user=new User();
        user.setUsername(username);
        user.setPassword(password);
        final String none="";
        user.setAvatar_img_name(none); user.setBg_img_name(none);  user.setSex(User.Sex.UNKNOWN.name().toLowerCase());
        user.setMajor(none); user.setGrade(-1); user.setUuid(SZUtil.generateUUID());
        userAccess.createUser(user);
        return new AbstractMap.SimpleEntry<>(user.getUuid(), user.getId());
    }

    @Override
    public void updateUserInfo(String uuid, Map<String, Object> detailKeyValueMap) throws BusinessException {
        if(uuid==null || detailKeyValueMap==null)
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        User user=userAccess.getUserByUUID(uuid);
        if(user==null)
            throw new BusinessException(404,"用户不存在");
        JSONObject j=new JSONObject(detailKeyValueMap);
        String username= j.getString(HttpSessionAttribute.USERNAME);
        if(username!=null) {
            if (!username.contentEquals(user.getUsername())&&userAccess.getUserByName(username)!=null)
                throw new BusinessException(409, "用户名已存在");
            if(username.isEmpty())
                throw new BusinessException(400, "用户名不能为空");
            user.setUsername(username);
        }


        String[] keys=new String[]{"description","sex","major","grade"};
        String content=j.getString(keys[0]);
        if(content!=null){
            user.setDescription(content);
        }
        content=j.getString(keys[1]);
        if(content!=null){
            user.setSex(content);
        }
        content=j.getString(keys[2]);
        if(content!=null){
            user.setMajor(content);
        }
        content=j.getString(keys[3]);
        if(content!=null){
            user.setGrade(Integer.parseInt(content));
        }

//        user.setAvatar_img_name(j.getString("avatar"));
//        user.setBg_img_name(j.getString("bg"));
        if(SZUtil.checkUserInfo(
                user.getUsername(),
                user.getSex(),
                user.getMajor(),
                user.getGrade(),
                user.getDescription())
        ){
            userAccess.updateUser(user);
        }
        else
            throw new BusinessException(400,"性别、年龄、个人介绍不符合要求");



    }

    @Override
    public void updateUserPassword(String uuid, String old_password, String new_password) throws BusinessException {
        if(uuid==null||old_password==null||new_password==null)
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        User u=userAccess.getUserByUUID(uuid);
        if(u==null){
            throw new BusinessException(404,"用户不存在");
        }
        if(u.getPassword().contentEquals(old_password)){
            if(SZUtil.checkPassword(new_password)){
                userAccess.updateUserPassword(u.getUuid(),new_password);
            }
            else
                throw new BusinessException(400,"密码不规范");
        }
        else
            throw new BusinessException(400,"旧密码错误");

    }

    @Override
    public Map.Entry<String,String> userLogin(String username, String password) throws BusinessException {
        if(username==null||password==null)
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        User user=userAccess.getUserByName(username);
        if(user==null||!user.getPassword().contentEquals(password))
            throw new BusinessException(400,"用户名或密码错误");

        return new AbstractMap.SimpleEntry<>(user.getUuid(),username);
    }

    @Override
    public User getUser(String uuid, String username) throws BusinessException {
        if(uuid==null&&username==null) //不接受空参数
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        User user=null;
        if(uuid!=null){
            user=userAccess.getUserByUUID(uuid);
        }
        if(user==null){
            if(username==null){
                throw new BusinessException(404,"用户不存在");
            }
            user=userAccess.getUserByName(username);
            if(user==null)
                throw new BusinessException(404,"用户不存在");
        }
        user.setPassword(null);
        return user;
    }

    @Override
    public JSONObject getUserInfo(String uuid, String username,String searcher_uuid) throws BusinessException {


        User user=getUser(uuid,username);
        JSONObject userInfo=new JSONObject();
        userInfo.put("username",user.getUsername());
        userInfo.put("uuid",user.getUuid());
        userInfo.put("sex",user.getSex());
        userInfo.put("grade",user.getGrade());
        userInfo.put("description",user.getDescription());
        userInfo.put("major",user.getMajor());
        userInfo.put("posts_num",user.getPosts_num());
        userInfo.put("avatar",user.getAvatar_img_name());
        userInfo.put("bg",user.getBg_img_name());
        userInfo.put("fans_num",user.getFans_num() );
        userInfo.put("follow_num",user.getFollow_num());

        //给出了searcher_uuid，查询关注关系,uuid!=null
        if(!user.getUuid().equals(searcher_uuid)){
            Follow follow=followAccess.getFollowByUUIDAndUserName(searcher_uuid,user.getUsername());
            userInfo.put("follow_status",follow!=null && follow.getStatus()==1 );
        }

        return userInfo;
    }

    @Override
    //当post 的imgs_name为空时，返回的String[]也为空
    public JSONArray getPosts(String uuid, String username, String keyword, int last_id, int limit) {
        ArrayList<User> userList = new ArrayList<>();
        ArrayList<Post> postList = new ArrayList<>();
        JSONArray jsonArray = new JSONArray();
        //将通过uuid与username单独查出结果并存到userList中
        if (username!=null){
            User tempUserList = userAccess.getUserByName(username);
            if (tempUserList!=null)
            userList.add(tempUserList);
        }
        if (uuid!=null){
            User user = userAccess.getUserByUUID(uuid);
            if (user!=null)
            userList.add(user);
        }

        //对userList中用户进行遍历，分别查出对应发帖记录
        for (User user:userList) {
            List<Post> postList1 = postAccess.searchPost(user.getId(),keyword,last_id,limit);
            if (postList1!=null) {
                for (Post post : postList1) {
                        postList.add(post);
                }
            }
        }
        //若uuid与username为空，则无需用到user表，直接对post表进行keyword搜索
        if (uuid==null&&username==null){
            List<Post> postList1 = postAccess.searchPost(null,keyword,last_id,limit);
            if (postList1!=null) {
                for (Post post : postList1) {
                    postList.add(post);
                }
            }
        }
        //将格式转为JSON并加入limit和last_id限制条件
        for (Post post:postList) {
            JSONObject jsonObject = getPost(post.getId(),0,0);
            jsonArray.add(jsonObject);
        }
        return jsonArray;
    }

    @Override
    public JSONObject getPost(int postId, int last_comment_id, int limit) {
        //limit小于0默认不分页,此处抛出异常更佳
        limit = limit >= 0 ? limit : 0;
        JSONObject jsonObject = new JSONObject();
        Post post = postAccess.getPostByPostId(postId);
        if (post==null){
            return jsonObject;
        }
        User u=userAccess.getUserById(post.getUser_id());
        jsonObject.put("post_id",post.getId());
        jsonObject.put("created_at",post.getCreated_at().toString());
        jsonObject.put("updated_at",post.getUpdated_at().toString());
        jsonObject.put("username",u.getUsername());
        jsonObject.put("avatar",u.getAvatar_img_name());
        jsonObject.put("content",post.getContent());
        jsonObject.put("comments_num",post.getComments_num());
        jsonObject.put("imgs_name",post.getImgs_name());
        JSONArray jsonArray = new JSONArray();
        //fixed
        List<Comment> commentList = commentAccess.getCommentsByPostId(postId,0);
        if (limit>0){
            //作出判断防止分页时越界,强制将分页范围缩小到正常范围
            last_comment_id = Math.max(last_comment_id,0);
            last_comment_id = Math.min(last_comment_id,commentList.size());
            int lastIndex = Math.min(last_comment_id+limit,commentList.size());
            commentList = commentList.subList(last_comment_id, lastIndex);
        }
        if (commentList!=null) {
            for (Comment c : commentList) {
                JSONObject json = new JSONObject();
                User _user=userAccess.getUserById(c.getUser_id());
                json.put("comment_id", c.getId());
                json.put("parent_id", c.getTarget_id());
                json.put("type", c.getType());
                json.put("content", c.getContent());
                json.put("comments_num", c.getComments_num());
                json.put("username", _user.getUsername());
                json.put("avatar",_user.getAvatar_img_name());
                json.put("img_name",c.getImg_name());
                json.put("created_at",c.getCreated_at().toString());
                json.put("updated_at",c.getUpdated_at().toString());

                jsonArray.add(json);
            }
        }
        jsonObject.put("comments",jsonArray);
        return jsonObject;
    }

    @Override
    public int savePost(String uuid, String content, String[] imgs_name) throws BusinessException {
        //String real_imgs_name = SZUtil.getRealImgsName(imgs_name);
        User user = userAccess.getUserByUUID(uuid);
        if (user==null){
            throw new BusinessException(404,"当前登录用户不存在");
        }
        if (content.length()>120||content==""){
            throw new BusinessException(400,"帖子内容为空或长度超过120字");
        }
        int post_id = -1;
        Post post = new Post();
        post.setContent(content);
        post.setUser_id(user.getId());
        post.setImgs_name(imgs_name);
//        post_id = postAccess.addPost(user.getId(),content,real_imgs_name);
        postAccess.addPost(post);
        post_id = post.getId();
        if (post_id!=-1){
            userAccess.updatePostNumber(user.getId(),true);
        }
        return post_id;
    }



    @Override
    public int updatePost(int post_id, String uuid, String content, String[] imgs_name) throws BusinessException {

        //String real_imgs_name = SZUtil.getRealImgsName(imgs_name);
        User user = userAccess.getUserByUUID(uuid);
        Post post = postAccess.getPostByPostId(post_id);
        if (post==null){
            throw new BusinessException(404,"帖子不存在");
        }
        if (user==null||user.getId()!=post.getUser_id()){
            throw new BusinessException(403,"没有权限修改该帖子");
        }
        if (content.length()>120||content.length()==0){
            throw new BusinessException(400,"帖子内容为空或长度超过120字");
        }
        postAccess.updatePost(post_id,content,imgs_name);
        return post_id;
    }

    @Override
    public void deletePost(int post_id, String uuid) throws BusinessException {
        Post post = postAccess.getPostByPostId(post_id);
        User user = userAccess.getUserById(post.getUser_id());
        if (user.getUuid().equals(uuid)){
            Timestamp currentTime = new Timestamp(System.currentTimeMillis());
            Timestamp deleted_at = postAccess.getPostByPostId(post_id).getDeleted_at();
            postAccess.updateDeleteTimeByPostId(post_id,currentTime);
            //未删除过时才对user中的postNum-1
            if (deleted_at==null) {
                userAccess.updatePostNumber(user.getId(), false);
            }
        }else {
            if (user.getUuid()==null){
                throw new BusinessException(404,"帖子不存在");
            }else {
                throw new BusinessException(403,"没有权限删除该帖子");
            }
        }
        return;
    }

    @Override
    public JSONObject getCommentById(int commentId,int last_comment_id, int limit) throws BusinessException {
        limit = limit > 0 ? limit : 1;
        Comment comment = commentAccess.getCommentById(commentId);
        if (comment == null)
            throw new BusinessException(404, "评论不存在");
        JSONObject json = new JSONObject();
        //n+1查询问题
        User u=userAccess.getUserById(comment.getUser_id());
        json.put("comment_id",comment.getId());
        json.put("parent_id",comment.getTarget_id());
        json.put("type",comment.getType());
        json.put("content",comment.getContent());
        json.put("comments_num",comment.getComments_num());
        json.put("username",u.getUsername());
        json.put("avatar",u.getAvatar_img_name());
        json.put("created_at",comment.getCreated_at().toString());
        json.put("updated_at",comment.getUpdated_at().toString());
        JSONObject comments= getComments(commentId,1,last_comment_id,limit);
        json.put("comments",comments.get("comments"));
        return json;
    }

    @Override
    public JSONObject getComments(int target_id, int type,int last_comment_id, int limit) throws BusinessException {
        JSONArray jsonArray=new JSONArray();
        List<Comment> commentsList;
        if(type==1) {
            commentsList=commentAccess.getCommentsByCommentId(target_id,limit);
        }
        else{
            commentsList=commentAccess.getCommentsByPostId(target_id,limit);
        }

        for(Comment c:commentsList){
            JSONObject json=new JSONObject();
            User u=userAccess.getUserById(c.getUser_id());
            json.put("comment_id",c.getId());
            json.put("parent_id",c.getTarget_id());
            json.put("type",c.getType());
            json.put("content",c.getContent());
            json.put("comments_num",c.getComments_num());
            json.put("username",u.getUsername());
            json.put("avatar",u.getAvatar_img_name());
            json.put("created_at",c.getCreated_at().toString());
            json.put("updated_at",c.getUpdated_at().toString());
            json.put("img_name", c.getImg_name());
            jsonArray.add(json);
        }
        JSONObject ret=new JSONObject();
        ret.put("comments",jsonArray);
        return ret;
    }

    @Override
    public int saveComment(int target_id,int target_type, String uuid, String content, String img_name) throws BusinessException {
        //检查参数规范
        //before()
        if(content==null||uuid==null){
            throw new BusinessException(400,"Bad Request");
        }

        //检查uuid是否存在
        User u=userAccess.getUserByUUID(uuid);

        Comment target_comment=commentAccess.getCommentById(target_id);
        boolean target_is_comment= target_type==1;
        //采用一种比较绕的方法判断target_id是评论id还是帖子id
//        if(target_comment==null){
//            //该方法依然不实际，因为如果目标是评论，
//            //并且在该条数据插入之前，被删除了，那么查询出来的结果
//            //依然可以是null
//            target_is_comment=false;
//        }

         if(u==null){
             throw new BusinessException(404,"用户不存在");
         }
         else{
             Comment c=new Comment();
             c.setTarget_id(target_id);
             c.setComments_num(1);
             c.setImg_name(img_name);
             c.setContent(content);
             c.setUser_id(u.getId());
             if(target_is_comment) {
                 c.setType(1);
                 c.setRoot_id(target_comment.getRoot_id());
                 commentAccess.adjustCommentNum(target_id,true); //增加评论下的评论数量
             }
             else {
                 c.setRoot_id(target_id);
                 c.setType(0); //这是帖子的评论
                 postAccess.adjustCommentsNum(target_id,true);
             }
             commentAccess.insertComment(c);
             return c.getId();
         }

    }

    @Override
    public void updateComment(int commentId, String uuid, String content, String img_name) throws BusinessException {
        //argument check
        if(uuid==null||content==null)
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());

        Comment c=commentAccess.getCommentById(commentId);
        User u=userAccess.getUserByUUID(uuid);
        if(c==null){
            throw new BusinessException(404,"评论不存在");
        }
        if(u==null||u.getId()!=c.getUser_id()){
            throw new BusinessException(403,"没有权限修改评论");
        }

        //检查长度
        int length=content.length();
        if(length>0&&length<=120){
            if(img_name==null)
                img_name=c.getImg_name();
            else if(img_name.isEmpty())
                img_name=null; //空串表示删除
            commentAccess.modifyCommentById(commentId,content,img_name);
        }
        else{
            throw new BusinessException(400,"帖子内容为空或长度超过120字");
        }

    }

    //unfinished impl
    @Override
    public void deleteComment(int commentId, String uuid) throws BusinessException {
        if(uuid==null){
            throw new BusinessException(400,"Bad Request");
        }
        Comment c=commentAccess.getCommentById(commentId);
        if(c==null){
            throw new BusinessException(404,"评论不存在");
        }
        User u=userAccess.getUserByUUID(uuid);
        if(u==null||u.getId()!=c.getUser_id()){
            throw new BusinessException(403,"没有权限删除评论");
        }
        commentAccess.deleteCommentById(commentId);
        if(c.getType()==1) {
            commentAccess.adjustCommentNum(c.getTarget_id(), false);
        }
        else{
            //stub adjust post's comment_nums
            //!!!!!!!!!!!!!!!!!!!!!!!!!!
            postAccess.adjustCommentsNum(c.getTarget_id(),false);
        }

    }

    @Override
    public JSONArray searchUsers(String uuid, String keyword, int limit) {
        if(keyword==null||keyword.isEmpty())
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        limit = limit <=0?1:limit;


        //keyword=keyword.replaceAll("%","\\%").replaceAll("_","\\_");
        List<UserSearchResult> result=userAccess.searchUser(uuid,keyword,limit);
        JSONArray jsonArray=new JSONArray();
        for(UserSearchResult usr:result){
            JSONObject j=new JSONObject();
            User u=usr.getUser();
            j.put("username",u.getUsername());
            j.put("uuid",u.getUuid());
            j.put("followed",usr.isFollowed());
            j.put("user_id",u.getId());
            j.put("sex",u.getSex());
            j.put("grade",u.getGrade());
            j.put("description",u.getDescription());
            j.put("posts_num",u.getPosts_num());
            j.put("avatar",u.getAvatar_img_name());
            jsonArray.add(j);
        }
        return jsonArray;
    }

    @Override
    public void updateAvatar(String uuid, String img_name) throws BusinessException {
        if(uuid==null||img_name==null||img_name.isEmpty())
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        User u=userAccess.getUserByUUID(uuid);
        if(u==null)
            throw new BusinessException(404,"用户不存在");
        userAccess.updateAvatarAndBackgroundImgName(uuid,img_name,null);
    }

    @Override
    public void updateBackgroundImageName(String uuid, String bg_img_name) throws BusinessException {
        if(uuid==null||bg_img_name==null||bg_img_name.isEmpty())
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.name());
        User u=userAccess.getUserByUUID(uuid);
        if(u==null)
            throw new BusinessException(404,"用户不存在");
        userAccess.updateAvatarAndBackgroundImgName(uuid,null,bg_img_name);
    }

    @Override
    public void followUser(String uuid, String username, int status) throws BusinessException {
        if(uuid==null || username==null )
            throw new BusinessException(400,"Bad Request");
        status = status ==1?1:0;

        User follower=userAccess.getUserByUUID(uuid);
        if(follower==null){
            throw new BusinessException(404,"uuid不存在");
        }
        User idol=userAccess.getUserByName(username);
        if(idol==null){
            throw new BusinessException(404,"用户不存在");
        }
        if(follower.getId()== idol.getId()){
            throw new BusinessException(400,"无法关注自己");
        }
        Follow follow=followAccess.getFollowByUUIDAndUserName(uuid,username);
        boolean subscribe=status==1;
        if(follow==null){
            follow=new Follow();
            follow.setTarget_id(idol.getId());
            follow.setUser_id(follower.getId());
            follow.setStatus(1);
            followAccess.insertFollow(follow);
        }
        else{
            if(follow.getStatus()!=status){
                followAccess.updateFollow(follow.getId(),status);
            }
            else{
                throw new BusinessException(400,"未关注/已关注该用户");
            }
        }
        //最后再修改用户粉丝和关注数。
        userAccess.subscribeUserById(idol.getId(), subscribe);
        userAccess.updateFollowNumById(follower.getId(), subscribe);
    }


    @Override
    public JSONArray getFollowJSONArray(String username, int limit) throws BusinessException {
        if(username==null||limit<=0){
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.toString());
        }
        List<FollowModel> followModels=followAccess.getFollowListByUserName(username,limit);
        JSONArray jsonArray=new JSONArray();
        if(followModels==null||followModels.isEmpty())
            return jsonArray;

        for(FollowModel model:followModels){
            JSONObject j=new JSONObject();
            User fan=model.getFan(); User idol=model.getIdol();
            j.put("follow_id",model.getId());
            j.put("user_id",fan.getId());
            j.put("user_username",fan.getUsername());
            j.put("user_avatar",fan.getAvatar_img_name());
            j.put("user_description",fan.getDescription());
            j.put("followed_user_id",idol.getId());
            j.put("followed_username",idol.getUsername());
            j.put("followed_user_description",idol.getDescription());
            j.put("followed_user_avatar",idol.getAvatar_img_name());
            j.put("status",1); //只返回1
            jsonArray.add(j);
        }

        return jsonArray;
    }

    @Override @Deprecated
    public List<Follow> getFollowList(int user_id, int limit) throws BusinessException {
        return null;
    }

    @Override @Deprecated
    public List<Follow> getFansList(int user_id, int limit) throws BusinessException {
        return null;
    }

    @Override
    public JSONArray getFansJSONArray(String username, int limit) throws BusinessException {
        if(username==null||limit<=0){
            throw new BusinessException(HttpStatus.BAD_REQUEST.value(), HttpStatus.BAD_REQUEST.toString());
        }
        List<FollowModel> followModels=followAccess.getFansListByUserName(username, limit);
        JSONArray jsonArray=new JSONArray();
        if(followModels==null||followModels.isEmpty())
            return jsonArray;

        for(FollowModel model:followModels){
            JSONObject j=new JSONObject();
            User fan=model.getFan(); User idol=model.getIdol();
            j.put("follow_id",model.getId());
            j.put("user_id",fan.getId());
            j.put("user_username",fan.getUsername());
            j.put("user_avatar",fan.getAvatar_img_name());
            j.put("user_description",fan.getDescription());
            j.put("followed_user_id",idol.getId());
            j.put("followed_username",idol.getUsername());
            j.put("followed_user_description",idol.getDescription());
            j.put("followed_user_avatar",idol.getAvatar_img_name());
            j.put("status",1); //只返回1
            jsonArray.add(j);
        }

        return jsonArray;
    }
}
